package com.junmoo.www.config.swagger;

import com.google.common.collect.Sets;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.OperationBuilder;
import springfox.documentation.schema.Example;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ApiListingScannerPlugin;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;

import java.util.*;

/**
 * 手动添加请求
 */
@Component
public class SwaggerAddtion implements ApiListingScannerPlugin {
    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }

    @Override
    public List<ApiDescription> apply(DocumentationContext context) {
        return Arrays.asList(
                setApiDescription( "login ","/auth/login","统一认证接口","登录","password","username"),
                setApiDescription( "logout ","/auth/logout","统一认证接口","登出")
        );

    }

    /**
     * 构建请求
     * @return
     */
    private ApiDescription  setApiDescription(String name,String url,String tag,String summary,String ...paramNames ){
        ApiDescription ApiDescription = new ApiDescription(name, url, "","",
                Collections.singletonList( setOperation(tag,summary,paramNames) ), false);
        return ApiDescription;
    }

    /**
     * 设置请求
     * @return
     */
    private Operation setOperation(String tag,String summary,String ...paramNames){
        Operation operation = new OperationBuilder(new CachingOperationNameGenerator())
                // 若不设置，所有的 Operation 共享一个系统默认的 uniqueId，
                // 因为CachingOperationNameGenerator 会缓存系统生成的第一个uniqueId；
                // 之后再生成 uniqueId 前，会先检查缓存；缓存中存在uniqueId 就使用缓存中的 uniqueId，否则生成新的 uniqueId ；
                // 只要 uniqueId 相同的 多个 Operation，只有最后一个生效
                // 所以 设置多个Operation时，必须设置 uniqueId 为唯一值
                .uniqueId(UUID.randomUUID().toString())
                .method(HttpMethod.POST)
                .summary(summary)
                .notes(summary)
                .consumes(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE)) // 接收参数格式
                .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE)) // 返回参数格式
                .tags(Sets.newHashSet(tag))
                .requestBody(setRequestBody())
                .requestParameters(setRequestParameters(paramNames))
                .responses(setResponses()).build();
        return  operation;

    }

    /**
     * 设置请求体
     * @return
     */
    private RequestBody setRequestBody(){
        String description = "";
        Set<Representation> representations = new HashSet<>();
        Boolean required = false;
        List<VendorExtension> extensions = new ArrayList<>();
        RequestBody requestBody = new RequestBody( description,  representations,  required, extensions);
        return requestBody;
    }

    /**
     *  设置请求参数
     * @param paramNames
     * @return
     */
    private Collection<RequestParameter> setRequestParameters(String ...paramNames){
        List<RequestParameter> list = new ArrayList<>();
        for (String name:paramNames ) {
            list.add( setBodyParameter(name) );
        }
        return list;
    }

    /**
     * 设置请求参数
     * @param name
     * @return
     */
    private RequestParameter setBodyParameter(String  name){
        String description="";
        ParameterType type=ParameterType.BODY;
        int precedence=1; //  优先权
        int parameterIndex=1;// 索引
        Boolean required=false;
        Boolean deprecated=false;
        Boolean hidden=false;
        ParameterSpecification parameterSpecification=new ParameterSpecification( null, null);
        Example scalarExample=new Example("id",  "summary", "description", "value",  "externalValue", "mediaType");
        Collection<Example> examples=new ArrayList<>();

        List<VendorExtension> extensions=new ArrayList<>();
        RequestParameter requestParameter = new RequestParameter(name,type,description,required,deprecated,hidden
                ,parameterSpecification,scalarExample,examples,precedence,extensions,parameterIndex);
        return requestParameter;
    }

    /**
     * 设置多个响应体，正常返回的响应体，异常返回的响应体等
     * @return
     */
    private Collection<Response> setResponses(){
        return Arrays.asList(setResponse());
    }

    /**
     * 设置响应体
     * @return
     */
    private Response setResponse(){
        String code = "200";
        String description = "成功";
        boolean isDefault = false;
        Collection<Header> headers = new ArrayList<>();
        Collection<Representation> representations = new ArrayList<>();
        Collection<Example> examples = new ArrayList<>();;
        Collection<VendorExtension> vendorExtensions = new ArrayList<>();
        Response response = new Response( code,  description,  isDefault,  headers,  representations,  examples, vendorExtensions);
        return response;
    }
}
